package zap

import (
	"fmt"
	"gitee.com/dennis-kk/service-box-go/util/slog"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"go.uber.org/zap/zapcore"
	"path"
	"strings"
	"time"
)

const (
	MinSplitLogFileSize = 1024 * 1024
)

type (
	Options struct {
		*slog.Options
		//set trace LogLevel
		zapTrace zapcore.Level
	}
)

//preprocess will preprocess for
func (o *Options) preprocess() {
	//process level
	o.LogLevel, _ = slog.GetLevel(o.LevelStr)
	//process file format
	if len(o.LogFile) == 0 {
		o.LogFile = "sbox_%Y-%m-%d-%H.log"
	} else {
		o.LogFile = strings.ToLower(o.LogFile)
		suffix := path.Ext(o.LogFile)
		fname := strings.TrimSuffix(o.LogFile, suffix)
		if len(suffix) == 0 {
			suffix = ".log"
		}
		// not contains custom time format
		if !strings.Contains(fname, "%") {
			o.LogFile = fname + "_%Y%m%d%H" + suffix
		}
	}
	//process traceLevel
	if level, err := slog.GetLevel(o.TraceLevel); err == nil {
		o.zapTrace = loggerToZapLevel(level)
	}

}

//zapLessThanWarn will filter level less than config
func (o *Options) zapLessThanWarn(level zapcore.Level) bool {
	//配置不允许都不可以输出
	if level < zapcore.Level(o.LogLevel) {
		return false
	}
	return level <= zapcore.WarnLevel && zapcore.Level(o.LogLevel) >= zapcore.DebugLevel
}

//zapGreaterThanWarn will filter level greater than config
func (o *Options) zapGreaterThanWarn(level zapcore.Level) bool {
	//配置不允许都不可以输出
	if level < zapcore.Level(o.LogLevel) {
		return false
	}
	return level > zapcore.WarnLevel
}

func (o *Options) zapEnableLevel(level zapcore.Level) bool {
	return level >= zapcore.Level(o.LogLevel)
}

//zapTimeFormatter format time
func (o *Options) zapTimeFormatter(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString(fmt.Sprintf("[%s]", t.Format(o.TimeFormat)))
}

//zapTimeRotateWriter will split log file with hour
func (o *Options) zapTimeRotateWriter() (zapcore.WriteSyncer, error) {

	var rops []rotatelogs.Option

	switch strings.ToLower(o.TimeSplit) {
	case "hour":
		rops = append(rops, rotatelogs.WithRotationTime(time.Hour))
	case "day":
		rops = append(rops, rotatelogs.WithRotationTime(24*time.Hour))
	default:
		rops = append(rops, rotatelogs.WithRotationTime(time.Hour))
	}

	if o.SizeSplit > 0 {
		if o.SizeSplit < MinSplitLogFileSize {
			o.SizeSplit = MinSplitLogFileSize
		}
		rops = append(rops, rotatelogs.WithRotationSize(o.SizeSplit))
	}

	rotator, err := rotatelogs.New(o.LogFile, rops...)

	if err != nil {
		return nil, err
	}

	return zapcore.AddSync(rotator), nil
}
